#include "RangeEnemy.h"

RangeEnemy::RangeEnemy(void) : newArrow(NULL){
	this->InitSprite(9);
	this->SetSprite(0, "images/Enemy/Minion/Range/enemyIdle1.tga");
	this->SetSprite(1, "images/Enemy/Minion/Range/enemyAttack1.tga");
	this->SetSprite(2, "images/Enemy/Minion/Range/enemyAttack2.tga");
	this->SetSprite(3, "images/Enemy/Minion/Range/enemyAttack3.tga");
	this->SetSprite(4, "images/Enemy/Minion/Range/enemyAttack4.tga");
	this->SetSprite(5, "images/Enemy/Minion/Range/enemyWalking1.tga");
	this->SetSprite(6, "images/Enemy/Minion/Range/enemyWalking2.tga");
	this->SetSprite(7, "images/Enemy/Minion/Range/enemyWalking3.tga");
	this->SetSprite(8, "images/Enemy/Minion/Range/enemyWalking4.tga");
	this->Init(Vector3D(0, 400, 0), 45, 60);
	this->SetLife(5.0f);
	this->SetAttackDamage(0.2f);

	weapon.InitSprite(3);
	weapon.SetSprite(0, "images/Enemy/Minion/Range/weapon1.tga");
	weapon.SetSprite(1, "images/Enemy/Minion/Range/weapon2.tga");
	weapon.SetSprite(2, "images/Enemy/Minion/Range/weapon3.tga");
	weapon.Init(this->GetPosition(), this->GetWidth(), this->GetHeight());

	spaceCheck.InitBox(this->GetPosition(), 2.0, this->GetHeight() / 2, 1.0);

	attackStart = false;
	attackTime = false;
	idleTime = false;

	this->SetSpeed(100.0f);
	this->SetLengthOfSight(LINE_OF_SIGHT);

	curState = IDLE;
	newState = IDLE;
}

RangeEnemy::~RangeEnemy(void){
	for(vector<Arrow *>::iterator itr = ArrowList.begin(); itr != ArrowList.end(); ++itr){
		delete (*itr);
	}
	ArrowList.clear();

	if(newArrow != NULL){
		delete newArrow;
		newArrow = NULL;
	}
}

void RangeEnemy::CreateArrow(void){
	newArrow = new Arrow;
	newArrow->SetPosition(Vector3D(weapon.GetPosition().x, weapon.GetPosition().y + (weapon.GetHeight() / 2), weapon.GetPosition().z) + this->oOff);

	if(this->invertImage)
		newArrow->SetDirection(Vector3D(1.0, this->GetDirection().y, 0.0));
	else
		newArrow->SetDirection(Vector3D(-1.0, this->GetDirection().y, 0.0));

	ArrowList.push_back(newArrow);
}

void RangeEnemy::Idle(void){
	if(this->GetOnGround()){
		if(!idleTime){
			this->SetSpriteImageNumber(0);

			for(vector<Object *>::iterator itr = TargetInfoList.begin(); itr != TargetInfoList.end(); ++itr){
				if(!(*itr)->GetBoundingBox(Object::FULLBODY).HitTest(this->GetBoundingBox(Object::FULLBODY))){
					rndNum = rand() % 100 + 1;
					if(rndNum < 25){
						this->SetDirection(Vector3D());
					}else{
						rndNum = rand() % 100 + 1;

						if(rndNum < 50)
							this->SetDirection(Vector3D(1.0, this->GetDirection().y, 0.0));
						else
							this->SetDirection(Vector3D(-1.0, this->GetDirection().y, 0.0));
					}
				}else{
					this->SetDirection(Vector3D());
				}
			}

			countdownTimer.StartTimer(0, 0, 5, 0);
			idleTime = true;
		}

		if(idleTime && countdownTimer.CheckIfTimerEnd()){
			//countdownTimer.StartTimer(0, 0, 5, 0);
			idleTime = false;
		}
	}
}

void RangeEnemy::Attack(void){
	if(!attackStart){
		this->SetDirection(Vector3D());

		this->SetSpriteImageNumber(0);
		countdownTimer.StartTimer(0, 0, 0, 500);

		weapon.invertImage = this->invertImage;

		attackStart = true;
	}

	if(attackStart && countdownTimer.CheckIfTimerEnd()){
		this->PlaySpriteAnimation(1, 4, 500);

		if(this->GetSpriteImageNumber() == 2){
			attackTime = true;
			renderWeapon = true;
		}

		if(this->animationFinished){
			this->CreateArrow();
			attackStart = false;
			this->SetSpriteImageNumber(0);
			newState = IDLE;
			attackTime = false;
			renderWeapon = false;
		}else if(attackTime){
			weapon.PlaySpriteAnimation(0, 2, 500);
			//weapon.SetSpriteImageNumber(1);
		}
	}
}

void RangeEnemy::RenderObject(void){
	Enemy::RenderObject();

	for(vector<Arrow *>::iterator itr = ArrowList.begin(); itr != ArrowList.end(); ++itr){
		(*itr)->RenderObject();
	}
}

void RangeEnemy::DropItemOnDeath(vector<PickUp *> *PickUpList){
	if(rand() % 100 + 1 < 25){
		this->CreatePickUp(Vector3D(this->GetPosition().x + this->oOff.x
									, this->GetPosition().y + this->oOff.y
									, this->GetPosition().z + this->oOff.z)
									, Item::no::ARROWHEAD, PickUpList);
	}

	if(rand() % 100 + 1 < 50){
		this->CreatePickUp(Vector3D(this->GetPosition().x + this->oOff.x + 30
									, this->GetPosition().y + this->oOff.y
									, this->GetPosition().z + this->oOff.z)
									, Item::no::LEATHER, PickUpList);
	}

	return;
};

bool RangeEnemy::UpdateObject(Vector3D offset, float elapsed){
	Enemy::UpdateObject(offset, elapsed);

	if(attackTime){
		weapon.UpdateObject(offset, elapsed);
	}

	for(vector<Object *>::iterator targetItr = TargetInfoList.begin(); targetItr != TargetInfoList.end(); ++targetItr){
		for(vector<Arrow *>::iterator itr = ArrowList.begin(); itr != ArrowList.end(); ++itr){
			if((*itr)->GetBoundingBox(Object::FULLBODY).HitTest((*targetItr)->GetBoundingBox(Object::FULLBODY))){
				(*targetItr)->ReduceLife(this->GetAttackDamage());

				delete (*itr);
				ArrowList.erase(itr);
				break;
			}
		}
	}

	for(vector<Arrow *>::iterator itr = ArrowList.begin(); itr != ArrowList.end(); ++itr){
		if((*itr)->UpdateObject(offset, elapsed)){
			delete (*itr);
			ArrowList.erase(itr);
			break;
		}
	}

	if(enemyDetected || attackStart){
		newState = ATTACK;
	}else{
		newState = IDLE;
	}

	if(curState != newState){
		countdownTimer.StopTimer();
		curState = newState;

		switch(newState){
			case IDLE:
				Board->SetMessage("IDLE", Message::ENEMY, id);
				break;
			case ATTACK:
				Board->SetMessage("ATTACK", Message::ENEMY, id);
				break;
		}
	}

	switch(curState){
		case IDLE:
			Idle();
			break;
		case ATTACK:
			Attack();
			break;
	}

	return false;
}